package com.guodi.model.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.guodi.common.utils.DateUtil;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.secure.utils.AuthUtil;
import com.guodi.model.entity.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.guodi.model.enums.UeProblemStatusEnum;
import com.guodi.model.mapper.DiagnosisProblemSceneMapper;
import com.guodi.model.mapper.UeProblemRecordsMapper;
import com.guodi.model.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guodi.model.vo.ApiProblemSceneIndicatorsVo;
import com.guodi.model.vo.UeProjectMangerVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
* 项目关联问题记录表 服务实现类
* @author lzy
* @date 2023-08-09
*/
@Service
public class UeProblemRecordsServiceImpl extends ServiceImpl<UeProblemRecordsMapper, UeProblemRecords> implements IUeProblemRecordsService {

    @Resource
    private UeProblemRecordsMapper ueProblemRecordsMapper;
    @Resource
    private DiagnosisProblemSceneMapper diagnosisProblemSceneMapper;

    @Resource
    private IIdtFillProblemService iIdtFillProblemService;
    @Resource
    private IIdtFillTaskService idtFillTaskService;
    @Resource
    private IIdtIndicatorsDirService iIdtIndicatorsDirService;
    @Resource @Lazy
    private IUeProjectMangerService ueProjectMangerService;
    @Resource
    private IIdtIndicatorsService idtIndicatorsService;


    /**
     * @描述: 保存项目自动分析问题记录并保存
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/8/22 14:49
     **/
    @Override
    public void calcProblemRecords(UeProjectManger projectManger) {
        List<String> problemIds = Arrays.asList(projectManger.getRespondProblem().split(";"));
        for(String problemId : problemIds){
            analysisProblemByProblemId(problemId,projectManger.getYear(),projectManger.getDivisionCode());
        }
    }


    /**
     * @描述: 保存或更新根据问题id记录各年份产生的问题记录
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/8/21 11:28
     **/
    private void analysisProblemByProblemId(String problemId, String yearStr, String divisionCode){
        //当前年
        Integer currentYear = Integer.valueOf(DateUtil.getYear());
        //当前节点年
        Integer year = Integer.valueOf(yearStr);
        //触发该问题的问题场景
        DiagnosisProblemScene problemScene = this.diagnosisProblemSceneMapper.getSceneByProblemId(problemId);
        String problemSceneId = problemScene.getId();

        List<UeProblemRecords> saveList = new ArrayList<>();
        List<UeProblemRecords> updateList = new ArrayList<>();

        do {

            //计算上一年是否存在该问题记录
            String lastYear = String.valueOf(year - 1);
            IdtFillTask lastTask = this.idtFillTaskService.getTaskByYearAndCode(lastYear, divisionCode);
            boolean lastYearProblemFlag = false;
            if(lastTask != null){
                lastYearProblemFlag = this.analysisStatusByYear(problemScene, lastYear, divisionCode);
            }


            //当前节点年份是否存在该问题
            IdtFillTask task = this.idtFillTaskService.getTaskByYearAndCode(String.valueOf(year), divisionCode);
            boolean yearProblemFlag = false;
            if(task != null){
                yearProblemFlag = this.analysisStatusByYear(problemScene, String.valueOf(year), divisionCode);
            }


            //获取记录状态
            String status = "";
            if(!lastYearProblemFlag && yearProblemFlag){
                //新增
                status = UeProblemStatusEnum.ADD.getCode();
            }
            if(lastYearProblemFlag && !yearProblemFlag){
                //解决
                status = UeProblemStatusEnum.SOLVE.getCode();
            }
            if(lastYearProblemFlag && yearProblemFlag){
                //如果上一年没有记录问题，则该记录为新增，否则计算状态变化
                LambdaQueryWrapper<UeProblemRecords> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(UeProblemRecords::getYear,lastYear);
                wrapper.eq(UeProblemRecords::getProblemId,problemSceneId);
                wrapper.eq(UeProblemRecords::getDivisionCode,divisionCode);
                UeProblemRecords records = this.getOne(wrapper);
                if(records == null){
                    if(CollectionUtils.isNotEmpty(saveList)){
                        Map<String,UeProblemRecords> yearToEntityMap = saveList.stream().collect(Collectors.toMap(UeProblemRecords::getYear, vo -> vo));
                        if(yearToEntityMap.get(lastYear) == null){
                            //新增
                            status = UeProblemStatusEnum.ADD.getCode();
                        } else {
                            //对比指标变化
                            status = this.compareStatusChanges(problemScene,lastYear,String.valueOf(year),divisionCode);
                        }
                    } else {
                        //新增
                        status = UeProblemStatusEnum.ADD.getCode();
                    }
                }else {
                    //对比指标变化
                    status = this.compareStatusChanges(problemScene,lastYear,String.valueOf(year),divisionCode);
                }
            }


            //记录问题前需要先查看是否已经存在记录了
            LambdaQueryWrapper<UeProblemRecords> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UeProblemRecords::getYear,String.valueOf(year));
            wrapper.eq(UeProblemRecords::getProblemId,problemSceneId);
            wrapper.eq(UeProblemRecords::getDivisionCode,divisionCode);
            UeProblemRecords records = this.getOne(wrapper);
            if(records != null){
                records.setStatus(status);
                records.setModifier(String.valueOf(AuthUtil.getUserId()));
                records.setModifyTime(new Date());
                updateList.add(records);
            }else {
                records = new UeProblemRecords();
                records.setStatus(status);
                records.setYear(String.valueOf(year));
                records.setDivisionCode(divisionCode);
                records.setProblemId(problemSceneId);
                records.setId(UuidUtil.get32UUID());
                records.setCreator(String.valueOf(AuthUtil.getUserId()));
                records.setCreateTime(new Date());
                saveList.add(records);
            }

            year++;

            if(UeProblemStatusEnum.SOLVE.getCode().equals(status)){
                break;
            }
        } while (year <= currentYear);

        if(CollectionUtils.isNotEmpty(updateList)){
            this.updateBatchById(updateList);
        }
        if(CollectionUtils.isNotEmpty(saveList)){
            this.saveBatch(saveList);
        }

    }

    /**
     * @描述: 计算某一年份是否存在该问题
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/8/18 16:06
     **/
    private boolean analysisStatusByYear(DiagnosisProblemScene problemScene, String year, String divisionCode) {
        //查出所有的该任务的指标值
        Map<String, ApiIndicatorsVal> fillValueMap = iIdtIndicatorsDirService.idToMapVal(year, divisionCode);
        //是否存在该问题
        boolean issue = iIdtFillProblemService.triggerIssue(problemScene, fillValueMap);
        return issue;
    }

    /**
     * @描述: 对比上一年与节点年的状态变化
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/8/21 15:17
     **/
    private String compareStatusChanges(DiagnosisProblemScene problemScene, String lastYear, String year, String divisionCode) {
        String status;
        String ruleJson = problemScene.getRelatedIndicators();
        List<ApiProblemSceneIndicatorsVo> rules = JSONArray.parseArray(ruleJson, ApiProblemSceneIndicatorsVo.class);

        List<String> idtIds = rules.stream().map(ApiProblemSceneIndicatorsVo::getIdtId).collect(Collectors.toList());
        List<IdtIndicators> idtIndicatorsList = this.ueProblemRecordsMapper.getIdtByIdtId(idtIds);

        if("单指标".equals(problemScene.getInfluenceFactor())){
            IdtIndicators idtIndicators = idtIndicatorsList.get(0);
            //当前年
            IdtMonitorValue idtMonitorValue = this.ueProblemRecordsMapper.getvalueByIdtId(idtIndicators.getId(), Integer.valueOf(year),divisionCode);
            //上一年
            IdtMonitorValue lastIdtMonitorValue = this.ueProblemRecordsMapper.getvalueByIdtId(idtIndicators.getId(), Integer.valueOf(lastYear),divisionCode);

            BigDecimal value = new BigDecimal(idtMonitorValue.getMonitorValue());
            BigDecimal lastValue = new BigDecimal(lastIdtMonitorValue.getMonitorValue());
            int result = value.compareTo(lastValue);


            if(result < 0){
                if("正向".equals(idtIndicators.getWarnRuleId())){
                    status = UeProblemStatusEnum.IMPROVE.getCode();
                }else {
                    status = UeProblemStatusEnum.DETERIORATE.getCode();
                }
            }else if(result > 0){
                if("正向".equals(idtIndicators.getWarnRuleId())){
                    status = UeProblemStatusEnum.DETERIORATE.getCode();
                }else {
                    status = UeProblemStatusEnum.IMPROVE.getCode();
                }
            }else {
                status = UeProblemStatusEnum.UNCHANGED.getCode();
            }
        }else {
            //多指标情况
            StringBuffer yearStr = new StringBuffer();
            StringBuffer lastYearStr = new StringBuffer();

            for(IdtIndicators idtIndicators : idtIndicatorsList){
                //当前年
                IdtMonitorValue idtMonitorValue = this.ueProblemRecordsMapper.getvalueByIdtId(idtIndicators.getId(), Integer.valueOf(year),divisionCode);
                //上一年
                IdtMonitorValue lastIdtMonitorValue = this.ueProblemRecordsMapper.getvalueByIdtId(idtIndicators.getId(), Integer.valueOf(lastYear),divisionCode);

                yearStr.append(idtMonitorValue.getMonitorValue()).append(" * (1/").append(idtIndicatorsList.size()).append(")").append(" + ");
                lastYearStr.append(lastIdtMonitorValue.getMonitorValue()).append(" * (1/").append(idtIndicatorsList.size()).append(")").append(" + ");

            }

            yearStr = yearStr.deleteCharAt(yearStr.length() - 2);
            lastYearStr = lastYearStr.deleteCharAt(lastYearStr.length() - 2);
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("js");

            String yearResult = "";
            String lastYearResult = "";
            try {
                Object yearObject = engine.eval(yearStr.toString());
                yearResult = String.format("%.2f",Double.valueOf(yearObject.toString()));

                Object lastYearObject = engine.eval(lastYearStr.toString());
                lastYearResult = String.format("%.2f",Double.valueOf(lastYearObject.toString()));
            } catch (ScriptException e) {
                e.printStackTrace();
            }

            BigDecimal value = new BigDecimal(yearResult);
            BigDecimal lastValue = new BigDecimal(lastYearResult);
            int result = value.compareTo(lastValue);
            if(result < 0){
                //恶化
                status = UeProblemStatusEnum.DETERIORATE.getCode();
            }else if(result > 0){
                //改善
                status = UeProblemStatusEnum.IMPROVE.getCode();
            }else {
                //不变
                status = UeProblemStatusEnum.UNCHANGED.getCode();
            }
        }

        return status;
    }


    /**
     * @描述: 查询列表
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/8/22 16:58
     **/
    @Override
    public List<UeProblemRecords> listByEntity(String year, String divisionCode, String name, String status) {
        List<UeProblemRecords> list = this.ueProblemRecordsMapper.listByEntity(year,divisionCode,name,status);
        for(UeProblemRecords records : list){
            records.setStatus(UeProblemStatusEnum.getStatusByCode(records.getStatus()));
        }
        return list;
    }

    @Override
    public List<ApiUeProblemRecords> getListByProblemId(String problemId) {
        DiagnosisProblemScene problemScene = this.diagnosisProblemSceneMapper.selectById(problemId);

        LambdaQueryWrapper<UeProblemRecords> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UeProblemRecords::getProblemId,problemId);
        wrapper.orderByAsc(UeProblemRecords::getYear);
        List<UeProblemRecords> list = this.list(wrapper);

        if(CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }

        //发现年
        String findYear;
        List<UeProblemRecords> collect1 = list.stream().filter(u -> u.getStatus().equals(UeProblemStatusEnum.ADD.getCode())).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(collect1)){
            findYear = collect1.get(0).getYear() + "年";
        }else {
            findYear = list.get(0).getYear() + "年";
        }

        //解决年
        String endYear;
        List<UeProblemRecords> collect2 = list.stream().filter(u -> u.getStatus().equals(UeProblemStatusEnum.SOLVE.getCode())).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(collect2)){
            endYear = collect2.get(0).getYear() + "年";
        }else {
            endYear = "未解决";
        }
        List<ApiUeProblemRecords> result = new ArrayList<>();
        for(UeProblemRecords records : list){
            ApiUeProblemRecords apiRecords = new ApiUeProblemRecords();
            apiRecords.setYear(records.getYear());
            apiRecords.setFindYear(findYear);
            apiRecords.setEndYear(endYear);
            apiRecords.setProblemNum(problemScene.getProblemNum());
            apiRecords.setProblemName(problemScene.getProblemName());
            apiRecords.setStatus(UeProblemStatusEnum.getStatusByCode(records.getStatus()));
            apiRecords.setDescribe(problemScene.getDescribe());
            result.add(apiRecords);
        }
        return result;
    }

    @Override
    public List<UeProjectMangerVo> getProjectsByProblemId(String problemId, String year, String divisionCode) {

        LambdaQueryWrapper<IdtFillProblem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(IdtFillProblem::getProblemId,problemId);
        wrapper.eq(IdtFillProblem::getDivisionCode,divisionCode);
        List<IdtFillProblem> idtFillProblems = this.iIdtFillProblemService.list(wrapper);

        Set<String> proBlemIdSet = idtFillProblems.stream().map(IdtFillProblem::getId).collect(Collectors.toSet());
        List<String> idtIdList = new ArrayList<>(proBlemIdSet);
        return this.ueProjectMangerService.listByProblemId(idtIdList);
    }

    @Override
    public List<ApiIndicatorsVal> getIndicatorsByProblemId(String problemId, String year, String divisionCode) {
        DiagnosisProblemScene problemScene = this.diagnosisProblemSceneMapper.selectById(problemId);
        String ruleJson = problemScene.getRelatedIndicators();
        List<ApiProblemSceneIndicatorsVo> rules = JSONArray.parseArray(ruleJson, ApiProblemSceneIndicatorsVo.class);
        List<String> idtIdList = rules.stream().map(ApiProblemSceneIndicatorsVo::getIdtId).collect(Collectors.toList());

        List<ApiIndicatorsVal> apiIndicatorsVals =  idtIndicatorsService.listIdtVal(idtIdList, year, divisionCode, false, false);
        this.updateWarnStatus(apiIndicatorsVals);
        return apiIndicatorsVals;
    }

    @Override
    public List<ApiIndicatorsVal> getIndicatorsInfo(String idtId, String year, String divisionCode, String startYear, String endYear) {
        // 根据指标编码去查指标
        LambdaQueryWrapper<IdtIndicators> queryWrapper = (new QueryWrapper()).lambda();
        queryWrapper.eq(IdtIndicators::getId,idtId);
        List<IdtIndicators> list = idtIndicatorsService.list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return  new ArrayList<>(0);
        }
        // 获取指标id
        Set<String> idtIdSet = list.stream().map(IdtIndicators::getId).collect(Collectors.toSet());
        LinkedList<String> idtIdList = new LinkedList<>(idtIdSet);
        List<ApiIndicatorsVal> apiIndicatorsVals = new ArrayList<>();
        // 查询数值
        if(StringUtils.isNotBlank(year) && StringUtils.isBlank(startYear) && StringUtils.isBlank(endYear)){
            apiIndicatorsVals = idtIndicatorsService.listIdtVal(idtIdList, year, divisionCode, false, false);
        }
        if(StringUtils.isBlank(year) && StringUtils.isNotBlank(startYear) && StringUtils.isNotBlank(endYear)){
            apiIndicatorsVals = idtIndicatorsService.listIdtVal(idtIdList, startYear, endYear, divisionCode, false, false);
        }
        this.updateWarnStatus(apiIndicatorsVals);
        return  apiIndicatorsVals;
    }

    /**
     * @描述: 计算指标预警状态
     * @入参:
     * @出参:
     * @作者: lzy
     * @日期: 2023/8/23 11:02
     **/
    private void updateWarnStatus(List<ApiIndicatorsVal> apiIndicatorsVals){
        if(apiIndicatorsVals!=null && apiIndicatorsVals.size()>0){
            // 20210806 添加指标预警规则
            apiIndicatorsVals.parallelStream().forEach(apiIndicatorsVal -> {
                if(StringUtils.isNotBlank(apiIndicatorsVal.getWarnRuleConfig())){
                    apiIndicatorsVal.setWarnStatus(idtIndicatorsService.updateWarnStatus(apiIndicatorsVal));
                }else {
                    apiIndicatorsVal.setWarnStatus("null,尚未配置规则");
                }
            });
        }
    }


}
